package com.notifier.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Base64;


/**
 * 钉钉工具包
 *
 * @author PC
 */
@Slf4j
@Component
public class DingSendUtil {

    /**
     * 请求地址以及access_token
     */
    @Value("${third.ding.web_hook}")
    private String webHook;
    /**
     * 密钥
     */
    @Value("${third.ding.secret}")
    private String secret;

    /**
     * 生成时间戳和验证信息
     *
     * @return
     * @throws Exception
     */
    private String encode() throws Exception {
        //获取时间戳
        Long timestamp = System.currentTimeMillis();
        //把时间戳和密钥拼接成字符串，中间加入一个换行符
        String stringToSign = timestamp + "\n" + secret;
        //声明一个Mac对象，用来操作字符串
        Mac mac = Mac.getInstance("HmacSHA256");
        //初始化，设置Mac对象操作的字符串是UTF-8类型，加密方式是SHA256
        mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256"));
        //把字符串转化成字节形式
        byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
        //新建一个Base64编码对象
        Base64.Encoder encoder = Base64.getEncoder();
        //把上面的字符串进行Base64加密后再进行URL编码
        String sign = URLEncoder.encode(encoder.encodeToString(signData), "UTF-8");
        String result = "&timestamp=" + timestamp + "&sign=" + sign;
        return result;
    }

    /**
     * param: message 要发送的信息
     * return: void 无返回值
     * 作用：把传入的message发送给钉钉机器人
     *
     * @param message
     */
    @Async
    public void dingRequest(String message) throws UnsupportedEncodingException {
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        String url = null;
        try {
            url = webHook + encode();
        } catch (Exception e) {
            log.warn("钉钉-生成时间戳和验证信息错误", e);
        }
        HttpPost httpPost = new HttpPost(url);
        //设置http的请求头，发送json字符串，编码UTF-8
        httpPost.setHeader("Content-Type", "application/json;charset=utf8");
        //生成json对象传入字符
        JSONObject result = new JSONObject();
        JSONObject text = new JSONObject();
        text.put("content", message);
        result.put("text", text);
        result.put("msgtype", "text");
        String jsonString = JSON.toJSONString(result);
        StringEntity entity = new StringEntity(jsonString, "UTF-8");
        //设置http请求的内容
        httpPost.setEntity(entity);
        // 响应模型
        CloseableHttpResponse response = null;
        try {
            // 由客户端执行(发送)Post请求
            response = httpClient.execute(httpPost);
            // 从响应模型中获取响应实体
            HttpEntity responseEntity = response.getEntity();
            if (responseEntity == null) {
                log.warn("钉钉发送日志错误,响应空");
                return;
            }
            String resultStr = EntityUtils.toString(responseEntity);
            JSONObject sendResultJson = JSONObject.parseObject(resultStr);
            if (!"0".equals(sendResultJson.getString("errcode"))) {
                log.warn("钉钉发送日志错误:" + resultStr);
            }
        } catch (Exception e) {
            log.warn("钉钉-错误信息发送错误:", e);
        } finally {
            try {
                // 释放资源
                if (httpClient != null) {
                    httpClient.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (Exception e) {
                log.warn("钉钉-释放资源-错误信息:", e);
            }
        }
    }
}
